elsocfandomcom-20200213-history
Music in Matlab
This is a page for anyone who gives a crap about MATLAB and music theory, who is keen to see more about how each work. Mild Disclaimer Some of this article will refer to theory that is covered in Digital Signal Processing (aka. DSP, first encountered properly in ELEC3104). Most of the things mentioned will be pretty basic though, so don't freak out too hard, because it will be easy for you to find out more about them using: *Wikipedia For simplicity's sake, this is not intended to be completely correct within the bounds of DSP, so any of my DSP chaps please don't think that I believe everything I am saying. I will, at least in the beginning, make some sweeping generalisations and enormous simplifications for the benefit of those people with no DSP experience. WillRowley 15:26, 19 June 2009 (UTC) Music? MATLAB? What are these and how are they related? So the first thing you need to know about the music and MATLAB: *Music consists of sounds. Simple, right? *"Sound" is the way you perceive, recognise and categorise vibrations in the air around you. *MATLAB is made of little men that live in your computer. Combining these three fundamental laws of nature, we can make MUSIC using MATLAB. A VERY Brief History Of Music (Including Some of the Science Within) Arguably the purest or most beautiful of all the vibrations (oscillations) is the sine (cosine) wave. You might remember me from subjects such as high school Advanced Mathematics, MATHxxxx, and Norman Wildberger's Youtube Channel. It should reveal itself to you at some point in your mathematical or electrical career, that all sounds (signals), can fairly well be constructed or described by the sum of sine waves of different phase or frequency. It was Pythagoras (the father of music and geometry?) who first realised that dividing a vibrating string in half created an "octave" of the original note. People probably already knew about the octave, and the inherent likeness of two notes separated by an octave interval, but it wasn't long before Pythagoras twigged onto the relationship that an "octave" interval in music consisted of a wave (in this case and in the case of many instruments, a standing wave on a string) oscillating at twice the frequency of the original. In Western Music there it is tradition to divide the "octave" interval into twelve smaller "equal" intervals (semitones). I believe this trend was also started by Pythagoras. It is not the only way. In some Eastern cultures the octave is divided into 24 smaller intervals (quartertones), and there are obviously countless ways to do it. It just so happens that Western music is pretty sweet and easy to work with, so I'll focus on that in this article. There also tends to be a tradition to primarily focus on the very popular "diatonic" scale/s. "Diatonic" describes any scale where all the notes (frequencies) therein are separated only by either tones or semitones. That is, there are no intervals between the notes of the scale that are larger than one whole tone. The "Major Scale" is the most famous of the diatonic scales primarily because it rules. In the common diatonic scale/s there are eight notes each (thus "octave"), with labels that you will soon see. You may have seen the Major Scale notated by its intervals: TTSTTTS (root TONE second TONE third SEMITONE fourth TONE fifth TONE sixth TONE seventh SEMITONE octave). The major scale is easy to locate on a piano by starting on C and playing only the white notes up to the next C. Not only does the major scale rule pretty hard, it is the basis for all other commonly accepted diatonic scales, the "modes". The modes basically consist of the Major Scale starting on different tonics (notes in the scale). For instance, the Dorian Mode has the interval pattern of TSTTTST (root TONE second SEMITONE third TONE fourth TONE fifth TONE sixth SEMITONE seventh TONE octave). You can see that it has started on what was the second note of the Major Scale, and played up until the octave is reached. You could achieve this on a piano by playing all of the white notes starting from D. More coming... Making MATLAB Make a Note Luckily for us, MATLAB is a program that loves maths, so the sine wave is easily accessible. Now to the fun part. "My First" Audio Function We can make a MATLAB function to produce a note/tone of a given pitch and length. It is at the basis of music that we find a relationship between pitch and frequency. The following function is very very basic (as you can see from the 3 lines of actual non-definition code). %This is how to declare a function in MATLAB. You place it in its own M-file, and in this case "y" is %the return variable - f1, fs, and seconds are all arguments function y = note(f1,fs,seconds) %This piece of code sets up a vector that, when cycled through at the sampling frequency (fs), will %take "seconds" seconds from start to finish n = 1:seconds*fs; %This creates the vector y y = sin(2*pi*(f1/fs)*n); %This MATLAB function produces the sound through your soundcard from the vector y at the sampling %frequency fs, there is another function "sound(...)" which does a similar thing but "soundsc(...)" %makes sure that it won't be played at RIDICULOUS levels, ie. it does something akin to normalising %all amplitudes within the vector y to the highest one (if you're interested read the source code) soundsc(y,fs); end Of course, this function is ONLY so simple because the majority of the work is done by the functions sin and soundsc. This function is mainly so that you can have something tangible to plug into MATLAB and satisfy your aural cravings. Multiple Frequencies Here's an alternate version which allows multiple frequency components for chords, harmonics, etc. For example to create an A major chord you pass the vector 277.12 329.63 440 as the f1 argument. %This is how to declare a function in MATLAB. You place it in its own M-file, and in this case "y" is %the return variable - f1, fs, and seconds are all arguments. f1 can be one frequency or a vector. function y = note(f1,fs,seconds) %This determines how many frequency components the sound will have len = length(f1); %This piece of code sets up a vector that, when cycled through at the sampling frequency (fs), will %take "seconds" seconds from start to finish n = 1:seconds*fs; %This creates the vector y y(n) = 0; for i = 1:len y = y + sin(2*pi*(f1(i)/fs)*n); end %This MATLAB function produces the sound through your soundcard from the vector y at the sampling %frequency fs, there is another function "sound(...)" which does a similar thing but "soundsc(...)" %makes sure that it won't be played at RIDICULOUS levels, ie. it does something akin to normalising %all amplitudes within the vector y to the highest one (if you're interested read the source code) soundsc(y,fs); end What's all the fs about? In the function above, you probably noticed the argument "fs" being thrown around a lot. This stands for sampling frequency and is of course more correctly written as f_s . Sampling frequency is fundamental in quantising an analogue (continuous) signal into a digital (discrete) one. If you want to learn more, I eagerly point you in the direction of wikipedia or any DSP resource. The important thing to note here is the line y = sin(2*pi*(f1/fs)*n);. You're probably used to seeing the continuous time sin wave written as sin(2pi*f*t + phi) or sin(omega*t + phi), where f corresponds to frequency, and omega corresponds to angular frequency where omega = 2pi*f. In the discrete domain, there is a quantity known as the "digital frequency", given by: \Theta = \frac{2 \pi f}{f_s} In the code y = sin(2*pi*(f1/fs)*n);, this can be seen in the "2*pi*(f1/fs)". The basics here are that the digital frequency corresponds to the analogue frequency given by f1 so long as it is sampled/reproduced at fs. It is important to note that the sampling frequency must be at least twice as large as the frequency given by f1, in accordance with the Nyquist Theorem A guide on how to use this function Given that humans cannot hear above around 22kHz, it is reasonably safe to use a sampling frequency of 44kHz. Given that a lot of audio codecs use 44.1kHz, this is an even better value to use. "Concert pitch" is defined by A being the note produced when a frequency of 440Hz is played, but I find this tone a little high even for my liking through headphones. So a good value for f1 might be 220Hz. A nice length is 1 second. Because. So you might call the above function by: note(220,44100,1); Sick of Notes, I Want Chords! Well it seems the call has come for code to create CHORDS. The way I could tell was when Eddie put code in for chords :D What is a chord? A chord is essentially any sound where there are multiple fundamental frequencies of oscillation. This definition means we can ignore the harmonics that are naturally present in fairly well every musical instrument (but not in MATLAB yet where your frequency components are very well defined). There are, however, some fairly well defined rules about certain chords that belong to (once again) the diatonic scale/s. This is simply because most people like chords that "sound nice". Chords that sound nice usually have some pretty nifty mathematics behind them! That roughly correlates to that if you were to inspect an audio wave on some kind of oscilloscope (or using "plot" in MATLAB), that if the sound LOOKS beautiful, it probably sounds it. Some musical types might refer to this mathematical splendour as "harmony", so let's stick with that. The Triad A triad is a chord that consists of three stacked thirds. Wow! If you're wondering what a third is, you weren't paying close attention in the Brief History section. Basically we start with a root note, eg. C, and step either 3 semitones or 4 semitones above that. Thirds come in two flavours, "minor" (3 semitones) and "major" (4 semitones), and are probably one of the most famous and recognisable intervals in music. They define the "tonality" of a scale or chord. The next note is another third interval above the third (thus, stacked thirds), or a fifth interval above the root! Fifth's come in three flavours, "diminished" (6 semitones), "perfect" (7 semitones), and "augmented" (8 semitones). It can be shown that the diatonic scale/s contain one of each of these flavours of thirds/fifths. Minor chords are easily recognisable as "sad", whereas major chords are "happy". The fifths have slightly less definable effects in terms of emotion, but are eventually equally recognisable in their own right. Deciding which third and fifth to use is based on what key (or diatonic scale) your music is in. Turning Semitones Into MATHS I believe it was covered briefly before that in western music, we tend to divide octaves up into twelve "equal" notes, or semitones. I say "equal" because they are not equally spaced on a linear scale, but they are equally spaced on a logarithmic scale. That logarithm happens to be base 2 (octave = twice frequency of root). Now I know some of you music chaps out there will be wondering "but what about Just Intonation?", and even those of you who have no idea what that means deserve to know. I will be focusing on Equal Temperament, rather than Just Intonation. To find out what those are, go ahead and look it up at Wikipedia. Right so we know an octave is defined as: f_O = f_f \cdot 2 Where f_O is the frequency one octave above f_f (the fundamental). If we want to divide our scale up into twelve logarithmically equal tones, we can say: f_h = f_f \cdot 2^{(s/12)} Where f_h is the desired frequency, and s is the number of semitones we would like in our interval. In MATLAB that would appear as something like this: f2 = f1*2^(c1/12); Build That Triad! Now we have all the tools we need to write a MATLAB function to build a triad, woo! All there is left is to decide how pretentious you are. I went for MAXIMUM PRETENCE, so my function (poorly) handles string labels for defining your third and fifth types. function y = triad(key, tonic, third, fifth, fs, seconds) %establish tonic if tonic 1 ton = 0; elseif tonic 2 ton = 2; elseif tonic 3 ton = 4; elseif tonic 4 ton = 5; elseif tonic 5 ton = 7; elseif tonic 6 ton = 9; elseif tonic 7 ton = 11; elseif tonic 8 ton = 12; end %establish third if third 'min' c1 = 3; elseif third 'maj' c1 = 4; end %establish fifth if fifth 'aug' c2 = 8; elseif fifth 'dim' c2 = 6; elseif fifth 'per' c2 = 7; end %Set up discrete-time vector n = 1:seconds*fs; f1 = key/fs; f1 = f1*2^(ton/12); f2 = f1*2^(c1/12); f3 = f1*2^(c2/12); A1 = 1; A2 = 1; A3 = 1; %Build your waveform y = A1*sin(2*pi*f1*n); y = y + A2*sin(2*pi*f2*n); y = y + A3*sin(2*pi*f3*n); soundsc(y,fs); end Those with a keen eye will note that the f_s handling has been moved for simplicity, and that the function also has a handle for the tonic that you would like your chord to start on. This was mainly for my own benefit but it basically will allow you to choose which note in the diatonic (major) scale of the key that you would like to start from, ie. selecting your modality. To construct an A major chord of 1 second length, sampling frequency 44100, you would use: triad(220, 1, 'maj', 'per', 44100, 1); To call the next chord in the same key you could thus use: triad(220, 2, 'min', 'per', 44100, 1); Notice that the "key" argument has stayed the same (it's in A), but I am using a different argument for "third". This is because in the key of A major lies the chord A major, followed by the chord B minor, which both have major fifths. You could construct a function where you simply enter triadFix(key, tonic, fs, seconds) and it builds the appropriate triad starting on the given tonic for that scale, but it is perhaps more instructive to leave it with the dynamic third arguments if you wanna get "experimental" or... you know... fluid. MORE TO COME - seventh chords - vector appending (song building) - general chord function rehash